package destiny.预测;

import java.util.ArrayList;
import java.util.List;

import destiny.干支;
import destiny.干支局;
import destiny.common.阴阳;
import destiny.五行.五行;
import destiny.干.十神;
import destiny.干.天干;
import destiny.干.天干五合;
import destiny.干.生旺死绝;
import destiny.支.地支;
import destiny.支.地支六冲;
import destiny.支.地支相刑;
import destiny.支.地支相害;

/**
 * 胡子模型：
 * 
 * 天地人三元论事，不脱五行阴阳，十天干也。
 * 
 * 以一至十和五十又五为天地之数，人元内藏五行，又五得六十数，是为天地人轮回之数。
 * 
 * 由十天干而得地支十二。故曰，地支藏干，是为人元。
 * 
 * 年月日时四柱干支以八字论命，实以天干论阴阳五行之生克乘侮也。
 * 
 * 年柱为根，月柱成枝，日柱开花，时柱得果。
 * 
 * 年岁日时柱不同，唯有月支映天时，四柱之中，以月支为提纲，故称“月提”。
 * 
 * 胎成得灵，择日而生，故日干为“我”，曰“日主”。
 * 
 * 四柱预测，首论干支关系，是为“十干之地支生旺死绝”，实为五行生克官印各宫顺逆而行，地支藏干由此而得。
 * 
 * 所谓生旺死绝论得令得地增力者，实为比劫帮身增力，五行相生。以通根透干为干支比劫助力，次论五行生克，故得令得地不用。
 * 
 * 地支为天干生发之根，以其为根故，彼此不易沟通，故不直论生克而先观局。
 * 
 * 三会三合又及半合，借一点天干之性沟通。得透方可成局。不透干不成局故，无“合绊”之说。
 * 
 * 地支局中，一点本气或冲，或合，或刑，或害，皆以五行生克为要：
 * 
 * 冲破合局者，对冲泄气而“泄多为克”故；
 * 
 * 所谓“合绊”不入刑冲克害者，五行过弱生者不生，克者不克也。
 * 
 * 地支已定，乃论天干，合同支藏，于是生克，命局成矣。
 * 
 * 复次，观命局，定用神，成格局，得神煞。不脱阴阳五行指事尔。
 * 
 * 先天命既定，后天又行运，命运成也。又及流年，命内“谈”宫，流年行运论“星”，预测论命可也。
 * 
 * 由古至今预测或以命运流年六柱，或以四柱命大小运胎元流年八柱，知其然而渐不知其所以然。
 * 
 * 地支为里，天干是表，由里及表。所谓预测，知其表象尔。故曰，心若淡然，苦者何谓？
 * 
 * 胡子以“其然”逆推“所以然”，以期自圆其说。附会而已。
 */
public class 四柱排盘 {
	protected int 年序;
	protected int 月序;
	protected int 日序;
	protected int 时序;

	protected 干支数[] 柱数;
	protected List<成局> 局集;

	public 干支数[] 柱数() {
		return 柱数;
	}

	public List<成局> 局集() {
		return 局集;
	}

	public 四柱排盘(干支[] 柱) {
		this(柱, Consts.四柱年序, Consts.四柱月序, Consts.四柱日序, Consts.四柱时序);
	}

	protected 四柱排盘(干支[] 柱, int 年序, int 月序, int 日序, int 时序) {
		this.年序 = 年序;
		this.月序 = 月序;
		this.日序 = 日序;
		this.时序 = 时序;

		this.柱数 = new 干支数[柱.length];

		for (int i = 0; i < 柱.length; ++i)
			柱数[i] = new 干支数(柱[i]);

		柱数[月序].支数().setWeight(Consts.月提权重);

		局集 = new ArrayList<成局>();
	}

	/**
	 * 组局
	 * 
	 * 1) 冲，各合见冲
	 * 
	 * 2) 三会局 > 三合局 > 旺半合（生地半合、墓地半合） > 六合 > 非旺半合（夹拱）
	 * 
	 * 3) 刑害入盘
	 * 
	 * 数论
	 * 
	 * 1) 各合论化
	 * 
	 * 2) 干支相克
	 */
	public void 运盘() {
		通根透干();
		/*
		 * 生旺死绝实为五行生克官印各宫顺逆而行，五行生克已论，故不用。
		 */
		// 天干生旺死绝();

		干支成局();
		各局调整();
		干支行局();

		/*
		 * 生克
		 */
		干支生克();

		用神();
	}

	/**
	 * 地支所藏之干，本静以待用，透出干头，则显其用矣。故干以通根为美，支以透出为贵。
	 * 
	 * FIXME : 十干生旺死绝得令得地将论通根，唯透干五行变动未论。
	 */
	private void 通根透干() {
		if (Consts._DEBUG) {
			System.out.println("== 通根透干 ==");
		}
		for (干支数 x : 柱数) {
			float evalve = 0;
			for (干支数 y : 柱数) {
				for (干数 z : y.支数().藏干数()) {
					if (z.术数().五行().equals(x.干数().术数().五行())) {
						evalve += Consts.有根得透加权 * z.getWeight() / Consts.四柱权重;
					}
				}
			}
			x.干数().setWeight((int) (x.干数().getWeight() * (1 + evalve)));
		}

		for (干支数 y : 柱数) {
			for (干数 z : y.支数().藏干数()) {
				float evalve = 0;
				for (int i = 0; i < 柱数.length; ++i) {
					if (i == 日序)
						continue;
					干数 x = 柱数[i].干数();
					if (z.天干().equals(x.天干())) {
						evalve += Consts.有根得透加权 * z.getWeight() / Consts.四柱权重;
					}
				}
				z.setWeight((int) (z.getWeight() * (1 + evalve)));
			}
		}
		if (Consts._DEBUG) {
			for (int i = 0; i < 柱数.length; ++i) {
				System.out.println(String.format("\t%s支：%s\t%s支：%s", 柱名(i),
						柱数[i].干数()._DEBUG(), 柱名(i), 柱数[i].支数()._DEBUG()));
			}
		}
	}

	/**************************** 生旺死绝 ********************************************/

	private void 天干生旺死绝() {
		if (Consts._DEBUG) {
			System.out.println("== 得令得地 ==");
		}
		/*
		 * 大运流年不入气，但需求地
		 */
		for (int i = 年序; i <= 时序; ++i) {
			干数 x = 柱数[i].干数();

			float evalve = 天干求地(x.天干(), i) + 天干求令(x.天干());
			x.setWeight((int) (x.getWeight() + Consts.四柱权重 * evalve));

			if (Consts._DEBUG) {
				System.out.println(String.format("\t%s干 : %s (求令 %f - 求地  %f)",
						柱名(i), x._DEBUG(), 天干求令(x.天干()), 天干求地(x.天干(), i)));
			}
		}
	}

	/**
	 * 得令：日干旺于月支，处长生、沐浴、冠带、临官、帝旺之地为得论。
	 */
	private float 天干求令(天干 干) {
		地支 月支 = 柱数[月序].支数().地支();
		生旺死绝 swsj = 生旺死绝.天干生旺死绝(干, 月支);
		if (生旺死绝.长生.equals(swsj) || 生旺死绝.沐浴.equals(swsj)
				|| 生旺死绝.冠带.equals(swsj) || 生旺死绝.临官.equals(swsj)
				|| 生旺死绝.帝旺.equals(swsj)) {

			return Consts.得令加权;
		}

		return 0;
	}

	/**
	 * 得地：日干在其余各支中得长生（须阳日干）、禄刃（禄神、羊刃），或逢墓库（阳日干逢墓库为有根，阴日干无气，故无根）。
	 * 
	 * FIXME: 库非墓，暂以墓代库 (TBD!!!)
	 */
	private float 天干求地(天干 干, int i) {
		float 衰减 = 1.0f, evalve = 0;
		for (int j = 年序; j <= 时序; ++j) {
			if (j == 月序)
				continue;

			switch (Math.abs(i - j)) {
			case 0:
				break;
			case 1:
				衰减 = Consts.隔柱衰减;
				break;
			default:
				衰减 = Consts.远柱衰减;
			}
			地支 支 = 柱数[j].支数().地支();
			if (阴阳.阳.equals(干.术数().阴阳()) && 生旺死绝.长生.equals(生旺死绝.天干生旺死绝(干, 支)))
				evalve += Consts.得地加权 * 衰减;

			if (生旺死绝.临官.equals(生旺死绝.天干生旺死绝(干, 支))
					|| 生旺死绝.帝旺.equals(生旺死绝.天干生旺死绝(干, 支)))
				evalve += Consts.得地加权 * 衰减;

			if (生旺死绝.墓.equals(生旺死绝.天干生旺死绝(干, 支))) {
				if (阴阳.阳.equals(干.术数().阴阳())) {
					evalve += Consts.得地加权 * 衰减;
				} else {
					evalve += Consts.得地加权 * Consts.无根衰减 * 衰减;
				}
			}
		}
		return evalve;
	}

	/**************************** 干支论局 ********************************************/

	private void 干支成局() {
		/**
		 * 成局
		 */
		局集.clear();

		天干五合();

		地支三会();
		地支三合();
		生地半合();
		墓地半合();
		非旺半合();

		地支冲();
		地支六合();
		地支刑害();
	}

	private List<成局> 局集(干支局... gzj) {
		List<成局> jus = new ArrayList<成局>();
		for (成局 ju : 局集) {
			for (干支局 j : gzj) {
				if (j.equals(ju.局()))
					jus.add(ju);
			}
		}
		return jus;
	}

	/**
	 * 三会局 > 三合局 > 旺半合（生地半合、墓地半合） > 六合 > 非旺半合（夹拱）
	 * 
	 * 各合见冲
	 * 
	 * 三会与六冲相见以会论。
	 * 
	 * 三合局与六冲相见除了合局中的子午卯酉被紧贴之支冲破外 ，均以合论。
	 * 
	 * 旺支半合紧贴但遇旺支紧贴而冲 ，以冲论。
	 * 
	 * 半合紧贴遇非旺支冲，冲不动，以半合论。
	 * 
	 * 半合中隔一无关紧要之支 ，若半合透出所化之五行（如亥卯半合中隔一他支为无用，但三合局为化木 ，若干透甲或乙则可），以半合有用论。反之无用。
	 * 
	 * 半合中隔冲支，以冲论。
	 * 
	 * 六冲与六合相见 ，除六合有力外，以冲论（如未年午月子时、午未合土未有力则不作子午冲 ）。
	 * 
	 * 鸳鸯合 四个地支各自找到合之对象
	 * 
	 * 月支时支争合日主，叫做妒合；争的不是日主，只叫争合而已；争合妒合，一律不能成化
	 * 
	 * 争合有序，支合有序：年、月、日、时
	 */
	private void 去冲(成局 ju, List<成局> 冲) {
		for (int i : ju.getIndexes()) {
			for (int j = 冲.size() - 1; j >= 0; --j) {
				成局 c = 冲.get(j);
				if (c.setOnIndex(i))
					冲.remove(j);
			}
		}
	}

	private boolean isNeighbor(成局 ju) {
		int[] is = ju.getIndexes();
		if (is.length != 2)
			return false;
		if (is[0] >= 年序 && is[1] <= 时序) {
			return (is[1] - is[0] == 1);
		}
		return true;
	}

	private void 各局调整() {
		List<成局> jus = new ArrayList<成局>();
		List<成局> 冲 = 局集(干支局.冲);

		int flag = 0, f;
		/*
		 * 三会与六冲相见以会论。
		 */
		for (成局 ju : 局集(干支局.三会局)) {
			flag |= ju.getId();
			jus.add(ju);
			去冲(ju, 冲);
		}
		/*
		 * 三合局与六冲相见除了合局中的子午卯酉被紧贴之支冲破外 ，均以合论。
		 */
		f = 0;
		for (成局 ju : 局集(干支局.三合局)) {
			if ((flag & ju.getId()) > 0)
				continue;
			boolean enabled = true;
			for (int i : ju.getIndexes()) {
				if (柱数[i].干支().地支().术数().五行().equals((五行) ju.getEnumInstance())) {
					for (成局 c : 冲) {
						if (c.setOnIndex(i)) {
							enabled = false;
							break;
						}
					}
				}
				if (!enabled)
					break;
			}
			if (!enabled)
				continue;
			f |= ju.getId();
			jus.add(ju);
			去冲(ju, 冲);
		}
		flag |= f;
		/*
		 * 旺支半合紧贴但遇旺支紧贴而冲 ，以冲论。
		 * 
		 * 半合紧贴遇非旺支冲，冲不动，以半合论。
		 * 
		 * 半合中隔冲支，以冲论。
		 */
		f = 0;
		for (成局 ju : 局集(干支局.生地半合, 干支局.墓地半合)) {
			if ((flag & ju.getId()) > 0)
				continue;
			boolean enabled = true;
			for (int i : ju.getIndexes()) {
				for (成局 c : 冲) {
					if (c.setOnIndex(i)
							&& 柱数[i].干支().地支().术数().五行()
									.equals((五行) ju.getEnumInstance())
							&& isNeighbor(ju)) {
						enabled = false;
						break;
					}
				}
				if (!enabled)
					break;
			}
			if (!enabled)
				continue;
			f |= ju.getId();
			jus.add(ju);
			去冲(ju, 冲);
		}
		flag |= f;
		/*
		 * 六冲与六合相见 ，除六合有力外，以冲论（如未年午月子时、午未合土未有力则不作子午冲 ）。
		 */
		f = 0;
		List<成局> jus2 = new ArrayList<成局>();
		for (成局 ju : 局集(干支局.地支六合)) {
			if ((flag & ju.getId()) > 0)
				continue;
			boolean enabled = true;
			for (int i : ju.getIndexes()) {
				for (成局 c : 冲) {
					if (c.setOnIndex(i)
							&& 柱数[i].干支().地支().术数().五行()
									.equals((五行) ju.getEnumInstance())) {
						enabled = false;
						break;
					}
				}
				if (!enabled)
					break;
			}
			if (!enabled)
				continue;
			去冲(ju, 冲);
			if ((f & ju.getId()) > 0) {
				// 争合、鸳鸯合
				jus2.add(ju);
			} else {
				f |= ju.getId();
				jus.add(ju);
			}
		}
		// 争合妒合
		for (成局 ju : jus2) {
			if ((f & ju.getId()) != ju.getId()) {
				// 争合
				f |= ju.getId();
				jus.add(ju);
			}
		}
		flag |= f;

		f = 0;
		for (成局 ju : 冲) {
			f |= ju.getId();
			jus.add(ju);
		}
		flag |= f;
		f = 0;
		for (成局 ju : 局集(干支局.非旺半合)) {
			if ((flag & ju.getId()) > 0)
				continue;
			f |= ju.getId();
			jus.add(ju);
		}
		flag |= f;
		for (成局 ju : 局集(干支局.刑)) {
			jus.add(ju);
		}
		for (成局 ju : 局集(干支局.害)) {
			jus.add(ju);
		}
		/*
		 * 鸳鸯合 四个地支各自找到合之对象
		 * 
		 * 月支时支争合日主，叫做妒合；争的不是日主，只叫争合而已；争合妒合，一律不能成化
		 * 
		 * 争合有序，支合有序：年、月、日、时
		 */
		f = 0;
		jus2 = new ArrayList<成局>();
		for (成局 ju : 局集(干支局.天干五合)) {
			if ((f & ju.getId()) > 0) {
				// 争合、鸳鸯合
				jus2.add(ju);
			} else {
				f |= ju.getId();
				jus.add(ju);
			}
		}
		// 争合妒合
		for (成局 ju : jus2) {
			if ((f & ju.getId()) != ju.getId()) {
				// 争合
				f |= ju.getId();
				jus.add(ju);
			}
		}

		局集 = jus;
	}

	private void 干支行局() {
		if (Consts._DEBUG) {
			System.out.println("== 干支行局 ==");
		}
		for (成局 ju : 局集(干支局.地支六合)) {
			for (int i : ju.getIndexes())
				柱数[i].支数().成局().add(ju);
		}
		for (成局 ju : 局集(干支局.天干五合)) {
			for (int i : ju.getIndexes())
				柱数[i].干数().成局().add(ju);
		}

		for (成局 ju : 局集) {
			if (干支局.三会局.equals(ju.局()) || 干支局.三合局.equals(ju.局())
					|| 干支局.生地半合.equals(ju.局()) || 干支局.墓地半合.equals(ju.局())
					|| 干支局.非旺半合.equals(ju.局()))
				地支合局化(ju);
			else if (干支局.冲.equals(ju.局()))
				地支行冲(ju);
			else if (干支局.地支六合.equals(ju.局()))
				地支六合化(ju);
			else if (干支局.天干五合.equals(ju.局()))
				天干五合化(ju);
			else {
				for (int i : ju.getIndexes())
					(ju.局().干局() ? 柱数[i].干数() : 柱数[i].支数()).成局().add(ju);
			}
			if (Consts._DEBUG) {
				System.out.println(String.format("\t%s", ju.局()));
				for (int i : ju.getIndexes()) {
					数 x = (ju.局().干局() ? 柱数[i].干数() : 柱数[i].支数());
					System.out.println(String.format("\t\t%s%s：\t%s", 柱名(i),
							(ju.局().干局() ? "干" : "支"), x._DEBUG()));
				}
			}

		}
	}

	private void 用神() {
		干数 日主 = 柱数[日序].干数();
		for (int i = 0; i < 柱数.length; ++i) {
			for (干数 干数 : 柱数[i].支数().藏干数()) {
				干数.神(十神.求神(日主, 干数));
			}
			if (i == 日序)
				continue;
			柱数[i].干数().神(十神.求神(日主, 柱数[i].干数()));
		}
	}

	/**************************** 天干 ************************************************/

	/**
	 * 干合宜紧贴
	 * 
	 * 遥合不化 有合之情，而无合之实
	 * 
	 * 月干时干争合日主，叫做妒合；争的不是日主，只叫争合而已
	 * 
	 * 争合有序，干合有序：年、月、日、时
	 * 
	 * 鸳鸯合 四个天干各自找到合之对象
	 */
	protected void 天干五合(int i, int j) {
		天干 x = 柱数[i].干数().天干();
		天干 y = 柱数[j].干数().天干();

		天干五合 h = 天干五合.合(x, y);
		if (null == h)
			return;
		局集.add(new 成局(干支局.天干五合, h, i, j, 柱数[i].干数(), 柱数[j].干数()));
	}

	/**
	 * FIXME: 遥合不化 有合之情，而无合之实，故不论 (TBD!!!)
	 */
	protected void 天干五合() {
		for (int i = 年序; i < 时序; ++i) {
			天干五合(i, i + 1);
		}
	}

	/**************************** 地支 ************************************************/
	/**
	 * 冲支中有子午卯酉本气之冲，子冲午，子主克，午受克；卯冲酉，卯受克，酉主克，有相战之冲意 ，最为激烈。
	 * 
	 * 寅申、巳亥之冲次之。而辰戌冲，丑未冲是土之本气冲 ，因激起而旺，无战克之意，但其中气、余气所藏干之间另以生克论。
	 * 
	 * FIXME: 远隔相冲是有冲之心无冲之力，克性不大，冲力为动而已，此处不论 (TBD!!!)
	 */
	protected void 地支冲() {
		for (int i = 年序; i < 时序; ++i) {
			地支冲(i, i + 1);
		}
	}

	protected void 地支冲(int i, int j) {
		支数 x = 柱数[i].支数(), y = 柱数[j].支数();
		地支六冲 ch = 地支六冲.冲(x.地支(), y.地支());
		if (null == ch)
			return;

		局集.add(new 成局(干支局.冲, ch, i, j, x, y));
	}

	private void 地支行冲(成局 ju) {
		int[] ids = ju.getIndexes();

		支数 x = 柱数[ids[0]].支数(), y = 柱数[ids[1]].支数();
		if (!干数.生克(x.藏干数()[0], y.藏干数()[0])) {
			干数.生克(x.藏干数()[1], y.藏干数()[1]);
			干数.生克(x.藏干数()[2], y.藏干数()[2]);
		}
		x.成局().add(ju);
		y.成局().add(ju);
	}

	private boolean 得天干引(五行 element) {
		for (int i = 0; i < 柱数.length; ++i) {
			if (element.equals(柱数[i].干数().天干().术数().五行()))
				return true;
		}
		return false;
	}

	private void 地支合局化(成局 ju) {
		for (int i : ju.getIndexes()) {
			支数 x = 柱数[i].支数();
			x.成局().add(ju);
			x.化((五行) ju.getEnumInstance());
		}
	}

	protected void 地支三会() {
		for (int i = 2; i < 柱数.length; ++i) {
			for (int j = 1; j < i; ++j) {
				for (int k = 0; k < j; ++k) {
					支数 x = 柱数[i].支数(), y = 柱数[j].支数(), z = 柱数[k].支数();
					五行 element = 地支.三会(x.地支(), y.地支(), z.地支());
					if ((null != element) && 得天干引(element))
						局集.add(new 成局(干支局.三会局, element, i, j, k, x, y, z));
				}
			}
		}
	}

	protected void 地支三合() {
		for (int i = 2; i < 柱数.length; ++i) {
			for (int j = 1; j < i; ++j) {
				for (int k = 0; k < j; ++k) {
					支数 x = 柱数[i].支数(), y = 柱数[j].支数(), z = 柱数[k].支数();
					五行 element = 地支.三合(x.地支(), y.地支(), z.地支());
					if ((null != element) && 得天干引(element))
						局集.add(new 成局(干支局.三合局, element, i, j, k, x, y, z));
				}
			}
		}
	}

	protected void 生地半合() {
		for (int i = 年序 + 1; i <= 时序; ++i) {
			for (int j = 年序; j < i; ++j) {
				生地半合(i, j);
			}
		}
	}

	protected void 生地半合(int i, int j) {
		支数 x = 柱数[i].支数(), y = 柱数[j].支数();
		五行 element = 地支.生地半合(x.地支(), y.地支());
		if ((null != element) && 得天干引(element))
			局集.add(new 成局(干支局.生地半合, element, i, j, x, y));
	}

	protected void 墓地半合() {
		for (int i = 年序 + 1; i <= 时序; ++i) {
			for (int j = 年序; j < i; ++j) {
				墓地半合(i, j);
			}
		}
	}

	protected void 墓地半合(int i, int j) {
		支数 x = 柱数[i].支数(), y = 柱数[j].支数();
		五行 element = 地支.墓地半合(x.地支(), y.地支());
		if ((null != element) && 得天干引(element))
			局集.add(new 成局(干支局.墓地半合, element, i, j, x, y));
	}

	protected void 非旺半合() {
		for (int i = 年序 + 1; i <= 时序; ++i) {
			for (int j = 年序; j < i; ++j) {
				非旺半合(i, j);
			}
		}
	}

	protected void 非旺半合(int i, int j) {
		支数 x = 柱数[i].支数(), y = 柱数[j].支数();
		五行 element = 地支.非旺半合(x.地支(), y.地支());
		if ((null != element) && 得天干引(element))
			局集.add(new 成局(干支局.非旺半合, element, i, j, x, y));
	}

	/**
	 * 六合必须紧贴
	 * 
	 * FIXME: 遥隔不能化，但有合之意，可以影响刑、冲，此处不论 (TBD!!!)
	 * 
	 * 妒合 争合日支叫妒合 研究婚姻问题时，要注意命局有无妒合，因男女都忌日支(夫妻宫)被妒合；如出现妒合，一生必有一次遭人横刀夺爱。
	 * 
	 * 凡妒合，一律不成化，其情不专也
	 * 
	 * 鸳鸯六合 鸳鸯合必须紧贴方能化
	 */
	protected void 地支六合() {
		for (int i = 年序; i < 时序; ++i) {
			地支六合(i, i + 1);
		}
	}

	protected void 地支六合(int i, int j) {
		支数 x = 柱数[i].支数(), y = 柱数[j].支数();
		五行 element = x.地支().六合(y.地支());

		if (null != element)
			局集.add(new 成局(干支局.地支六合, element, i, j, x, y));
	}

	private void 地支刑害() {
		for (int i = 1; i < 柱数.length; ++i) {
			for (int j = 0; j < i; ++j) {
				支数 x = 柱数[i].支数(), y = 柱数[j].支数();

				地支相刑 刑 = 地支相刑.刑(x.地支(), y.地支());
				if (null != 刑) {
					局集.add(new 成局(干支局.刑, 刑, i, j, x, y));
				}

				地支相害 害 = 地支相害.害(x.地支(), y.地支());
				if (null != 害) {
					局集.add(new 成局(干支局.害, 害, i, j, x, y));
				}
			}
		}
	}

	/**************************** 合化 ************************************************/

	/**
	 * 争合妒合，一律不能成化
	 * 
	 * 月提有引则化（余气亦可）月提无引不化，只是合住
	 * 
	 * 月提犯化神，不能成化 天干相合，月提余气有化神成引，但月提主气刚好正克化出之神，亦不能成化
	 * 
	 * 所化五行在其余三合或三会成局也可论化
	 * 
	 * 合而能化,则原来两干之本性已失
	 * 
	 * 若合而不化，无根(主气)之干, 原气尽失：不再克他干，不克直坐地支，亦不受直坐地支生扶
	 * 
	 * 若合而不化，有根(主气)之干, 原性犹在
	 * 
	 * 日主被合 无论化与不化，日主之原性不失
	 */
	private void 天干五合化(成局 ju) {
		支数 月提 = 柱数[月序].支数();

		int[] ids = ju.getIndexes();
		int i = ids[0], j = ids[1];
		干数 x = 柱数[i].干数(), y = 柱数[j].干数();

		成局[] 成局 = x.成局(干支局.天干五合);

		boolean 成化 = true;
		/*
		 * 争合妒合，一律不能成化
		 */
		switch (成局.length) {
		case 0:
			return;
		case 1:
			成化 = y.成局(干支局.天干五合).length == 1;
			break;
		default:
			成化 = false;
		}

		if (!成化) {
			/*
			 * 日主被合 无论化与不化，日主之原性不失
			 * 
			 * 天干合化生克此处不论
			 */
			if (i != 日序)
				x.setWeight((int) (x.getWeight() * Consts.合绊泄气));
			if (j != 日序)
				y.setWeight((int) (y.getWeight() * Consts.合绊泄气));
			return;
		}

		天干五合 h = (天干五合) 成局[0].getEnumInstance();

		/*
		 * 必须通根于月提(主气或余气均可)，方能成化。
		 * 
		 * 月提有引则化（余气亦可）月提无引不化，只是合住
		 */

		if (月提.有根(h.五行())) {
			/*
			 * 月提犯化神，不能成化 天干相合
			 * 
			 * 月提余气有化神成引，但月提主气刚好正克化出之神，亦不能成化
			 */
			if (月提.地支().术数().五行().克().equals(h.五行()))
				成化 = false;
		} else {
			/*
			 * 所化五行在其余三合或三会成局也可论化
			 */
			成化 = false;
			for (成局 s : 局集) {
				if ((s.局().equals(干支局.三合局) || s.局().equals(干支局.三会局))
						&& s.getEnumInstance().equals(h.五行())) {
					成化 = true;
					break;
				}
			}
		}

		if (成化) {
			/*
			 * 合而能化,则原来两干之本性已失
			 */
			if (i != 日序)
				x.化(h.五行());
			if (j != 日序)
				y.化(h.五行());
		} else {
			if (i != 日序)
				x.setWeight((int) (x.getWeight() * Consts.合绊泄气));
			if (j != 日序)
				y.setWeight((int) (y.getWeight() * Consts.合绊泄气));
		}
	}

	/**
	 * 合而成化必须同时具备两个条件，缺一不可
	 * 
	 * (1) 化神与月提主气相同，或得月提主气生扶
	 * 
	 * 即月提为金，只能化金、水 即月提为水，只能化水、木 即月提为木，只能化木、火 即月提为火，只能化火、土 即月提为土，只能化土、金
	 * 
	 * (2) 天干有化神引化 化神为阴则化为阴，化神为阳则化为阳
	 * 
	 * 注：凡有合，先看有无化神，其次再看月提，没有化神，一定是合而不化，即合住；再清楚一点，即是合的双方，都被绊着，在命局中不能起作用。
	 */

	private void 合绊(干数 x, 干数 y) {
		干数.生克(x, y);
		x.setWeight((int) (x.getWeight() * Consts.合绊泄气));
		y.setWeight((int) (y.getWeight() * Consts.合绊泄气));
	}

	private void 地支六合化(成局 ju) {
		地支 月提 = 柱数[月序].支数().地支();

		五行[] 化神 = { 月提.术数().五行(), 月提.术数().五行().生() };

		int[] ids = ju.getIndexes();
		支数 x = 柱数[ids[0]].支数(), y = 柱数[ids[1]].支数();
		成局[] 成局 = x.成局(干支局.地支六合);

		boolean 成化 = true;
		/*
		 * 争合妒合，一律不能成化
		 */
		switch (成局.length) {
		case 0:
			return;
		case 1:
			成化 = y.成局(干支局.地支六合).length == 1;
			break;
		default:
			成化 = false;
		}
		if (!成化) {
			合绊(x.藏干数()[0], y.藏干数()[0]);
			return;
		}

		五行 ele = (五行) 成局[0].getEnumInstance();

		阴阳 yinYang = null;
		成化 = false;
		/*
		 * 化神与月提主气相同，或得月提主气生扶
		 */
		if (ele.equals(化神[0]) || ele.equals(化神[1])) {
			/*
			 * 天干有化神引化 化神为阴则化为阴，化神为阳则化为阳
			 */
			for (int k = 0; k < 柱数.length; ++k) {
				干数 干数 = 柱数[k].干数();
				if (ele.equals(干数.术数().五行())) {
					成化 = true;
					yinYang = 干数.术数().阴阳();
					break;
				}
			}
		}

		if (成化) {
			x.化(ele, yinYang);
			y.化(ele, yinYang);
		} else {
			合绊(x.藏干数()[0], y.藏干数()[0]);
		}
	}

	/**************************** 生克 ************************************************/

	/**
	 * 天干相生：邻干之生，其生力大于隔干；同性之生，其生力大于异性；生者减气，受生者得益。
	 * 
	 * 天干相克：两干相克，邻干力大，隔干次之 ，远干无力；两干同性相克之力大于异性相克；两干相克均受损伤、受克损伤大；
	 * 
	 * 隔干之克， 中隔之干化克则不以克论。如丙火隔干克庚金，中隔土，是土泄火气而生金气，连续相生，故以生论不以克论。
	 * 
	 * 克中有合，合去克则不作克论。如丙火克庚金，但柱中有辛，丙辛合水，水是克火的，丙火克不了庚金，故不以克论。
	 * 
	 * 吉神相克为凶，凶神相克为吉。
	 * 
	 * 地支为根，天干为果
	 * 
	 * 地气入宫，不论生克
	 * 
	 * 地支对天干生扶受克
	 * 
	 * 天干互争，论生克
	 * 
	 * 综合成五行
	 */
	protected void 干支生克() {
		if (Consts._DEBUG) {
			System.out.println("== 干支生克 ==");
		}

		干数 x, y;
		/*
		 * 直坐干支生克
		 */
		for (int i = 0; i < 柱数.length; ++i) {
			干支生克(i, i, 1);
		}

		/*
		 * 天干生克
		 */
		boolean[] 生克 = new boolean[柱数.length];
		for (int i = 年序 + 1; i <= 时序; ++i) {

			x = 柱数[i].干数();
			y = 柱数[i - 1].干数();
			if (干数.生克(x, y)) {
				生克[i] = true;
				生克[i - 1] = true;
				if (Consts._DEBUG) {
					System.out.println(String.format("\t%s干 : %s \t- %s干 : %s",
							柱名(i), x._DEBUG(), 柱名(i - 1), y._DEBUG()));
				}
			}
		}

		for (int i = 年序 + 2; i <= 时序; ++i) {
			if (生克[i] && 生克[i - 2])
				continue;

			x = 柱数[i].干数();
			y = 柱数[i - 2].干数();
			if (干数.生克(x, y, Consts.隔柱衰减)) {
				生克[i] = true;
				生克[i - 2] = true;
				if (Consts._DEBUG) {
					System.out.println(String.format("\t%s干 : %s \t- %s干 : %s",
							柱名(i), x._DEBUG(), 柱名(i - 2), y._DEBUG()));
				}
			}
		}
		for (int i = 年序 + 3; i <= 时序; ++i) {
			if (生克[i] && 生克[i - 3])
				continue;

			x = 柱数[i].干数();
			y = 柱数[i - 3].干数();
			if (干数.生克(x, y, Consts.远柱衰减)) {
				if (Consts._DEBUG) {
					System.out.println(String.format("\t%s干 : %s \t- %s干 : %s",
							柱名(i), x._DEBUG(), 柱名(i - 3), y._DEBUG()));
				}
			}
		}

		/*
		 * 支对干论生克
		 */
		for (int i = 年序; i <= 时序; ++i) {
			for (int j = 年序; j <= 时序; ++j) {
				if (i == j)
					continue;

				干支生克(i, j, (Math.abs(i - j) > 1) ? Consts.远柱衰减 : Consts.隔柱衰减);
			}
		}
	}

	protected void 干支生克(int 干序, int 支序, float 衰减) {
		数 x = 柱数[干序].干数(), y = 柱数[支序].支数();

		boolean changed = false;
		// 藏干因合化而变
		for (干数 z : ((支数) y).藏干数()) {
			if (干数.生克((干数) x, z, 衰减)) {
				changed = true;
			}
		}
		if (changed && Consts._DEBUG) {
			System.out.println(String.format("\t%s干 : %s \t- %s支藏干（含合化）%s",
					柱名(干序), x._DEBUG(), 柱名(支序), y._DEBUG()));
		}
	}

	public String 柱名(int i) {
		return 柱名2(i);
	}

	public static String 柱名2(int i) {
		switch (i) {
		case Consts.四柱年序:
			return "年";
		case Consts.四柱月序:
			return "月";
		case Consts.四柱日序:
			return "日";
		case Consts.四柱时序:
			return "时";
		}
		return "";
	}

	public static String 宫名2(int i, boolean 干, boolean 乾造) {
		if (i >= Consts.四柱年序 && i <= Consts.四柱时序)
			return Consts.四柱宫[i][乾造 && 干 ? 0 : 干 ? 1 : 乾造 ? 1 : 0];
		return "";
	}

	/**
	 * 太极判为天地，一气分有阴阳。
	 * 
	 * 日干为主，专论财官。
	 * 
	 * 月支取格，乃分贵贱。 有格不正者，败。
	 * 
	 * 无格有用者，成。
	 * 
	 * 有官，莫寻格局。
	 * 
	 * 有格局，喜官星。
	 * 
	 * 官印财食无破，清高。
	 * 
	 * 杀伤梟刃，用之为吉。
	 * 
	 * 善恶相交，喜去杀而从善。
	 * 
	 * 吉凶混杂，忌害吉以化凶。
	 * 
	 * 有官有杀，宜身旺，制杀为奇。
	 * 
	 * 有官有印，畏财兴，助财为祸。
	 * 
	 * 身强杀浅，杀运无妨。
	 * 
	 * 杀重身轻，制乡为福。
	 * 
	 * 身旺印多，喜行财地。
	 * 
	 * 财多身弱，畏入财乡。
	 * 
	 * 男逢比劫伤官，剋妻害子。
	 * 
	 * 女犯伤官偏印，丧子刑夫。
	 * 
	 * 幼失双亲，财星太重。
	 * 
	 * 为人孤剋，身旺无依。
	 * 
	 * 年冲月令，离祖成家。
	 * 
	 * 日破提冲，弦断再续。
	 * 
	 * 时日对冲，伤妻剋子。
	 * 
	 * 日通月令，得祖安身。
	 * 
	 * 木遇春长，遇庚辛反假为权。
	 * 
	 * 火归夏生，见壬癸能为福厚。
	 * 
	 * 土逢辰戌丑未，木重成名。
	 * 
	 * 金坐申酉之中，火乡发福。
	 * 
	 * 水居亥子，戊己难侵。
	 * 
	 * 身坐休囚，平生未济。
	 * 
	 * 身旺喜逢禄马。
	 * 
	 * 身弱忌见财官。
	 * 
	 * 得时俱为旺论。
	 * 
	 * 失令便作衰看。
	 * 
	 * 四柱无根，得时为旺。
	 * 
	 * 日干无气，遇劫为强。
	 * 
	 * 身弱喜印。
	 * 
	 * 主旺宜官。
	 * 
	 * 财官印綬，破则无功。
	 * 
	 * 杀伤梟劫，去之为福。
	 * 
	 * 甲乙秋生金透露，水木火运荣昌。
	 * 
	 * 丙丁冬降水汪洋，火土木方贵显。
	 * 
	 * 戊己春生，西南方有救。
	 * 
	 * 庚辛夏长，水土运无伤。
	 * 
	 * 壬癸逢于土旺，金木宜荣。
	 * 
	 * 身弱有印，杀旺无伤；忌行财地。
	 * 
	 * 伤官伤尽，行官运以无妨。
	 * 
	 * 伤官用印宜去财。
	 * 
	 * 伤官用财宜去印。
	 * 
	 * 是或，伤官财印俱彰，将何发福；身旺者用财，身弱者用印。用财去印，用印去财，方发弥福；正所谓喜者存之，憎者去之。
	 * 
	 * 财多身弱，身旺以为荣。
	 * 
	 * 身旺财衰，财旺乡而发福。
	 * 
	 * 重犯官星，只宜制伏。
	 * 
	 * 食神叠见，须忌官乡。
	 * 
	 * 顽金无火，大用不成。
	 * 
	 * 强木无金，清名难著。
	 * 
	 * 水多得土，财多蓄。
	 * 
	 * 火焰逢波（水星），禄位高。
	 * 
	 * 有官有印，无破无荣。
	 * 
	 * 无印无官，有格取贵。
	 * 
	 * 阳刃格喜偏官。
	 * 
	 * 金神最宜制伏。
	 * 
	 * 杂气财官，刑冲则发。
	 * 
	 * 官贵太盛，旺处必倾。
	 * 
	 * 身太旺，喜见财官。
	 * 
	 * 主太柔，不宜禄马。
	 * 
	 * 旺官旺印与旺财，入墓有祸。
	 * 
	 * 伤官食神并身旺，遇库兴灾。
	 * 
	 * 运贵在于支取。
	 * 
	 * 岁重向乎干求。
	 * 
	 * 印多者，行财而发。
	 * 
	 * 财旺者，遇比何妨。
	 * 
	 * 格清局正，富贵荣华。
	 * 
	 * 印旺官旺，声名特达。
	 * 
	 * 合官，非为贵取。
	 * 
	 * 合杀，莫作凶推。
	 * 
	 * 桃花带杀，喜淫奔。
	 * 
	 * 华盖逢空，多刻剥。
	 * 
	 * 平生不发，八字休囚。
	 * 
	 * 一世无权，身衰遇鬼。
	 * 
	 * 身旺者，则宜泄、宜伤。
	 * 
	 * 身衰者，则喜扶、喜助。
	 * 
	 * 稟中和，莫令太过不及。
	 * 
	 * 若遵此法推详，祸福验如影响。
	 */
}
